using FNVHash
using Base.Test

@test fnv32([0x01,0x47,0x6c,0x10,0xf3]) == 0
@test fnv32([0xfd, 0x45, 0x41, 0x08, 0xa0]) == 0


# Taken from http://www.isthe.com/chongo/src/fnv/test_fnv.c ...

TEST(s) = s

function TEST0(s)
    a = Vector{UInt8}(s)
    push!(a, 0x00)
end

R10(s::AbstractString) = s^10
R500(s::AbstractString) = s^500

R10(s) = repeat(s, outer=[10])
R500(s) = repeat(s, outer=[500])

input = Any[
  TEST(""),
  TEST("a"),
  TEST("b"),
  TEST("c"),
  TEST("d"),
  TEST("e"),
  TEST("f"),
  TEST("fo"),
  TEST("foo"),
  TEST("foob"),
  TEST("fooba"),
  TEST("foobar"),
  TEST0(""),
  TEST0("a"),
  TEST0("b"),
  TEST0("c"),
  TEST0("d"),
  TEST0("e"),
  TEST0("f"),
  TEST0("fo"),
  TEST0("foo"),
  TEST0("foob"),
  TEST0("fooba"),
  TEST0("foobar"),
  TEST("ch"),
  TEST("cho"),
  TEST("chon"),
  TEST("chong"),
  TEST("chongo"),
  TEST("chongo "),
  TEST("chongo w"),
  TEST("chongo wa"),
  TEST("chongo was"),
  TEST("chongo was "),
  TEST("chongo was h"),
  TEST("chongo was he"),
  TEST("chongo was her"),
  TEST("chongo was here"),
  TEST("chongo was here!"),
  TEST("chongo was here!\n"),
  TEST0("ch"),
  TEST0("cho"),
  TEST0("chon"),
  TEST0("chong"),
  TEST0("chongo"),
  TEST0("chongo "),
  TEST0("chongo w"),
  TEST0("chongo wa"),
  TEST0("chongo was"),
  TEST0("chongo was "),
  TEST0("chongo was h"),
  TEST0("chongo was he"),
  TEST0("chongo was her"),
  TEST0("chongo was here"),
  TEST0("chongo was here!"),
  TEST0("chongo was here!\n"),
  TEST("cu"),
  TEST("cur"),
  TEST("curd"),
  TEST("curds"),
  TEST("curds "),
  TEST("curds a"),
  TEST("curds an"),
  TEST("curds and"),
  TEST("curds and "),
  TEST("curds and w"),
  TEST("curds and wh"),
  TEST("curds and whe"),
  TEST("curds and whey"),
  TEST("curds and whey\n"),
  TEST0("cu"),
  TEST0("cur"),
  TEST0("curd"),
  TEST0("curds"),
  TEST0("curds "),
  TEST0("curds a"),
  TEST0("curds an"),
  TEST0("curds and"),
  TEST0("curds and "),
  TEST0("curds and w"),
  TEST0("curds and wh"),
  TEST0("curds and whe"),
  TEST0("curds and whey"),
  TEST0("curds and whey\n"),
  TEST("hi"), TEST0("hi"),
  TEST("hello"), TEST0("hello"),
  TEST(b"\xff\x00\x00\x01"), TEST(b"\x01\x00\x00\xff"),
  TEST(b"\xff\x00\x00\x02"), TEST(b"\x02\x00\x00\xff"),
  TEST(b"\xff\x00\x00\x03"), TEST(b"\x03\x00\x00\xff"),
  TEST(b"\xff\x00\x00\x04"), TEST(b"\x04\x00\x00\xff"),
  TEST(b"\x40\x51\x4e\x44"), TEST(b"\x44\x4e\x51\x40"),
  TEST(b"\x40\x51\x4e\x4a"), TEST(b"\x4a\x4e\x51\x40"),
  TEST(b"\x40\x51\x4e\x54"), TEST(b"\x54\x4e\x51\x40"),
  TEST("127.0.0.1"), TEST0("127.0.0.1"),
  TEST("127.0.0.2"), TEST0("127.0.0.2"),
  TEST("127.0.0.3"), TEST0("127.0.0.3"),
  TEST("64.81.78.68"), TEST0("64.81.78.68"),
  TEST("64.81.78.74"), TEST0("64.81.78.74"),
  TEST("64.81.78.84"), TEST0("64.81.78.84"),
  TEST("feedface"), TEST0("feedface"),
  TEST("feedfacedaffdeed"), TEST0("feedfacedaffdeed"),
  TEST("feedfacedeadbeef"), TEST0("feedfacedeadbeef"),
  TEST("line 1\nline 2\nline 3"),
  TEST("chongo <Landon Curt Noll> /\\../\\"),
  TEST0("chongo <Landon Curt Noll> /\\../\\"),
  TEST("chongo (Landon Curt Noll) /\\../\\"),
  TEST0("chongo (Landon Curt Noll) /\\../\\"),
  TEST("http://antwrp.gsfc.nasa.gov/apod/astropix.html"),
  TEST("http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash"),
  TEST("http://epod.usra.edu/"),
  TEST("http://exoplanet.eu/"),
  TEST("http://hvo.wr.usgs.gov/cam3/"),
  TEST("http://hvo.wr.usgs.gov/cams/HMcam/"),
  TEST("http://hvo.wr.usgs.gov/kilauea/update/deformation.html"),
  TEST("http://hvo.wr.usgs.gov/kilauea/update/images.html"),
  TEST("http://hvo.wr.usgs.gov/kilauea/update/maps.html"),
  TEST("http://hvo.wr.usgs.gov/volcanowatch/current_issue.html"),
  TEST("http://neo.jpl.nasa.gov/risk/"),
  TEST("http://norvig.com/21-days.html"),
  TEST("http://primes.utm.edu/curios/home.php"),
  TEST("http://slashdot.org/"),
  TEST("http://tux.wr.usgs.gov/Maps/155.25-19.5.html"),
  TEST("http://volcano.wr.usgs.gov/kilaueastatus.php"),
  TEST("http://www.avo.alaska.edu/activity/Redoubt.php"),
  TEST("http://www.dilbert.com/fast/"),
  TEST("http://www.fourmilab.ch/gravitation/orbits/"),
  TEST("http://www.fpoa.net/"),
  TEST("http://www.ioccc.org/index.html"),
  TEST("http://www.isthe.com/cgi-bin/number.cgi"),
  TEST("http://www.isthe.com/chongo/bio.html"),
  TEST("http://www.isthe.com/chongo/index.html"),
  TEST("http://www.isthe.com/chongo/src/calc/lucas-calc"),
  TEST("http://www.isthe.com/chongo/tech/astro/venus2004.html"),
  TEST("http://www.isthe.com/chongo/tech/astro/vita.html"),
  TEST("http://www.isthe.com/chongo/tech/comp/c/expert.html"),
  TEST("http://www.isthe.com/chongo/tech/comp/calc/index.html"),
  TEST("http://www.isthe.com/chongo/tech/comp/fnv/index.html"),
  TEST("http://www.isthe.com/chongo/tech/math/number/howhigh.html"),
  TEST("http://www.isthe.com/chongo/tech/math/number/number.html"),
  TEST("http://www.isthe.com/chongo/tech/math/prime/mersenne.html"),
  TEST("http://www.isthe.com/chongo/tech/math/prime/mersenne.html#largest"),
  TEST("http://www.lavarnd.org/cgi-bin/corpspeak.cgi"),
  TEST("http://www.lavarnd.org/cgi-bin/haiku.cgi"),
  TEST("http://www.lavarnd.org/cgi-bin/rand-none.cgi"),
  TEST("http://www.lavarnd.org/cgi-bin/randdist.cgi"),
  TEST("http://www.lavarnd.org/index.html"),
  TEST("http://www.lavarnd.org/what/nist-test.html"),
  TEST("http://www.macosxhints.com/"),
  TEST("http://www.mellis.com/"),
  TEST("http://www.nature.nps.gov/air/webcams/parks/havoso2alert/havoalert.cfm"),
  TEST("http://www.nature.nps.gov/air/webcams/parks/havoso2alert/timelines_24.cfm"),
  TEST("http://www.paulnoll.com/"),
  TEST("http://www.pepysdiary.com/"),
  TEST("http://www.sciencenews.org/index/home/activity/view"),
  TEST("http://www.skyandtelescope.com/"),
  TEST("http://www.sput.nl/~rob/sirius.html"),
  TEST("http://www.systemexperts.com/"),
  TEST("http://www.tq-international.com/phpBB3/index.php"),
  TEST("http://www.travelquesttours.com/index.htm"),
  TEST("http://www.wunderground.com/global/stations/89606.html"),
  TEST(R10("21701")),
  TEST(R10("M21701")),
  TEST(R10("2^21701-1")),
  TEST(R10(b"\x54\xc5")),
  TEST(R10(b"\xc5\x54")),
  TEST(R10("23209")),
  TEST(R10("M23209")),
  TEST(R10("2^23209-1")),
  TEST(R10(b"\x5a\xa9")),
  TEST(R10(b"\xa9\x5a")),
  TEST(R10("391581216093")),
  TEST(R10("391581*2^216093-1")),
  TEST(R10(b"\x05\xf9\x9d\x03\x4c\x81")),
  TEST(R10("FEDCBA9876543210")),
  TEST(R10(b"\xfe\xdc\xba\x98\x76\x54\x32\x10")),
  TEST(R10("EFCDAB8967452301")),
  TEST(R10(b"\xef\xcd\xab\x89\x67\x45\x23\x01")),
  TEST(R10("0123456789ABCDEF")),
  TEST(R10(b"\x01\x23\x45\x67\x89\xab\xcd\xef")),
  TEST(R10("1032547698BADCFE")),
  TEST(R10(b"\x10\x32\x54\x76\x98\xba\xdc\xfe")),
  TEST(R500(b"\x00")),
  TEST(R500(b"\x07")),
  TEST(R500("~")),
  TEST(R500(b"\x7f"))
]

results = [
    0x811c9dc5,
    0x050c5d7e,
    0x050c5d7d,
    0x050c5d7c,
    0x050c5d7b,
    0x050c5d7a,
    0x050c5d79,
    0x6b772514,
    0x408f5e13,
    0xb4b1178b,
    0xfdc80fb0,
    0x31f0b262,
    0x050c5d1f,
    0x70772d5a,
    0x6f772bc7,
    0x6e772a34,
    0x6d7728a1,
    0x6c77270e,
    0x6b77257b,
    0x408f5e7c,
    0xb4b117e9,
    0xfdc80fd1,
    0x31f0b210,
    0xffe8d046,
    0x6e772a5c,
    0x4197aebb,
    0xfcc8100f,
    0xfdf147fa,
    0xbcd44ee1,
    0x23382c13,
    0x846d619e,
    0x1630abdb,
    0xc99e89b2,
    0x1692c316,
    0x9f091bca,
    0x2556be9b,
    0x628e0e73,
    0x98a0bf6c,
    0xb10d5725,
    0xdd002f35,
    0x4197aed4,
    0xfcc81061,
    0xfdf1479d,
    0xbcd44e8e,
    0x23382c33,
    0x846d61e9,
    0x1630abba,
    0xc99e89c1,
    0x1692c336,
    0x9f091ba2,
    0x2556befe,
    0x628e0e01,
    0x98a0bf09,
    0xb10d5704,
    0xdd002f3f,
    0x1c4a506f,
    0x6e772a41,
    0x26978421,
    0xe184ff97,
    0x9b5e5ac6,
    0x5b88e592,
    0xaa8164b7,
    0x20b18c7b,
    0xf28025c5,
    0x84bb753f,
    0x3219925a,
    0x384163c6,
    0x54f010d7,
    0x8cea820c,
    0xe12ab8ee,
    0x26978453,
    0xe184fff3,
    0x9b5e5ab5,
    0x5b88e5b2,
    0xaa8164d6,
    0x20b18c15,
    0xf28025a1,
    0x84bb751f,
    0x3219922d,
    0x384163ae,
    0x54f010b2,
    0x8cea8275,
    0xe12ab8e4,
    0x64411eaa,
    0x6977223c,
    0x428ae474,
    0xb6fa7167,
    0x73408525,
    0xb78320a1,
    0x0caf4135,
    0xb78320a2,
    0xcdc88e80,
    0xb78320a3,
    0x8ee1dbcb,
    0xb78320a4,
    0x4ffb2716,
    0x860632aa,
    0xcc2c5c64,
    0x860632a4,
    0x2a7ec4a6,
    0x860632ba,
    0xfefe8e14,
    0x0a3cffd8,
    0xf606c108,
    0x0a3cffdb,
    0xf906c5c1,
    0x0a3cffda,
    0xf806c42e,
    0xc07167d7,
    0xc9867775,
    0xbf716668,
    0xc78435b8,
    0xc6717155,
    0xb99568cf,
    0x7662e0d6,
    0x33a7f0e2,
    0xc2732f95,
    0xb053e78f,
    0x3a19c02a,
    0xa089821e,
    0x31ae8f83,
    0x995fa9c4,
    0x35983f8c,
    0x5036a251,
    0x97018583,
    0xb4448d60,
    0x025dfe59,
    0xc5eab3af,
    0x7d21ba1e,
    0x7704cddb,
    0xd0071bfe,
    0x0ff3774c,
    0xb0fea0ea,
    0x58177303,
    0x4f599cda,
    0x3e590a47,
    0x965595f8,
    0xc37f178d,
    0x9711dd26,
    0x23c99b7f,
    0x6e568b17,
    0x43f0245b,
    0xbcb7a001,
    0x12e6dffe,
    0x0792f2d6,
    0xb966936b,
    0x46439ac5,
    0x728d49af,
    0xd33745c9,
    0xbc382a57,
    0x4bda1d31,
    0xce35ccae,
    0x3b6eed94,
    0x445c9c58,
    0x3db8bf9d,
    0x2dee116d,
    0xc18738da,
    0x5b156176,
    0x2aa7d593,
    0xb2409658,
    0xe1489528,
    0xfe1ee07e,
    0xe8842315,
    0x3a6a63a2,
    0x06d2c18c,
    0xf8ef7225,
    0x843d3300,
    0xbb24f7ae,
    0x878c0ec9,
    0xb557810f,
    0x57423246,
    0x87f7505e,
    0xbb809f20,
    0x8932abb5,
    0x0a9b3aa0,
    0xb8682a24,
    0xa7ac1c56,
    0x11409252,
    0xa987f517,
    0xf309e7ed,
    0xc9e8f417,
    0x7f447bdd,
    0xb929adc5,
    0x57022879,
    0xdcfd2c49,
    0x6edafff5,
    0xf04fb1f1,
    0xfb7de8b9,
    0xc5f1d7e9,
    0x32c1f439,
    0x7fd3eb7d,
    0x81597da5,
    0x05eb7a25,
    0x9c0fa1b5,
    0x53ccb1c5,
    0xfabece15,
    0x4ad745a5,
    0xe5bdc495,
    0x23b3c0a5,
    0xfa823dd5,
    0x0c6c58b9,
    0xe2dbccd5,
    0xdb7f50f9
]

for (i, r) in zip(input, results)
    @test fnv32(i) == r
end
